package org.xx.armory.commons;

import javax.management.JMException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.Validators.notBlank;
import static org.xx.armory.commons.Validators.notNull;

/**
 * MBean相关的工具方法。
 */
public final class MBeanUtils {
    private MBeanUtils() {
    }

    /**
     * 构造用于注册MBean的ObjectName。
     *
     * @param domain
     *         域名，自动去掉首尾空格并转换为小写。
     * @param type
     *         MBean的类型，自动去掉首尾空格。
     * @param name
     *         MBean的名字，自动去掉首尾空格。
     * @throws IllegalArgumentException
     *         如果参数{@code bean}是{@code null}，如果参数{@code domain}是{@code null}或者只包含空白字符，如果参数{@code type}和{@code name}都是{@code null}或只包含 空白字符。
     */
    private static String createObjectName(
            String domain,
            String type,
            String name
    ) {
        domain = notBlank(domain, "domain").trim();
        type = trimToEmpty(type);
        name = trimToEmpty(name);

        if (type.isEmpty() && name.isEmpty()) {
            throw new IllegalArgumentException("type and name cannot be null or empty both");
        }

        final StringBuilder result = new StringBuilder();

        result.append(domain).append(':');
        if (!type.isEmpty()) {
            result.append("type=").append(type).append(',');
        }
        if (!name.isEmpty()) {
            result.append("name=").append(name);
        }

        final int lastPos = result.length() - 1;
        if (result.charAt(lastPos) == ',') {
            result.deleteCharAt(lastPos);
        }

        return result.toString();
    }

    /**
     * 注册MBean。
     *
     * @param bean
     *         待注册的MBean。
     * @param domain
     *         域名。
     * @param type
     *         MBean的类型。
     * @param name
     *         MBean的名字。
     * @throws IllegalArgumentException
     *         如果参数{@code bean}是{@code null}，如果参数{@code domain}是{@code null}或者只包含空白字符。
     * @throws IllegalStateException
     *         如果注册MBean出错。
     * @see ManagementFactory#getPlatformMBeanServer()
     * @see javax.management.MBeanServer#registerMBean(Object, ObjectName)
     */
    public static void registerMBean(
            Object bean,
            String domain,
            String type,
            String name
    ) {
        notNull(bean, "bean");

        try {
            final String objectName = createObjectName(domain, type, name);
            ManagementFactory.getPlatformMBeanServer().registerMBean(bean, new ObjectName(objectName));
        } catch (JMException ex) {
            throw new IllegalStateException("cannot register MBean: domain=" + domain + ",type=" + type + ",name=" + name, ex);
        }
    }

    /**
     * 反注册MBean。
     *
     * @param domain
     *         域名。
     * @param type
     *         MBean的类型。
     * @param name
     *         MBean的名字。
     * @throws IllegalArgumentException
     *         如果参数{@code bean}是{@code null}，如果参数{@code name}是{@code null}或者只包含空白字符。
     * @throws IllegalStateException
     *         如果反注册MBean出错。
     * @see ManagementFactory#getPlatformMBeanServer()
     * @see javax.management.MBeanServer#registerMBean(Object, ObjectName)
     */
    public static void unregisterMBean(
            String domain,
            String type,
            String name
    ) {
        type = trimToEmpty(type);
        name = notBlank(name, "name").trim();

        try {
            final String objectName = createObjectName(domain, type, name);
            ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(objectName));
        } catch (JMException ex) {
            throw new IllegalStateException("cannot register MBean: domain=" + domain + ",type=" + type + ",name=" + name, ex);
        }
    }
}
